package org.example.offical.doc.ai.service;

import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.memory.chat.TokenWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModelName;
import dev.langchain4j.model.openai.OpenAiTokenizer;
import dev.langchain4j.model.output.structured.Description;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.example.offical.doc.ModelUtils;

/**
 * @author superMan
 * @since fish_temp_since
 */
public class SimpleAiService {

    public static void main(String[] args) {
        ChatLanguageModel openAiDemoModel = ModelUtils.getOpenAiDemoModel();
        // 自动创建一个代理对象
        Assistant assistant = AiServices.create(Assistant.class, openAiDemoModel);
        System.out.println(assistant.chat("python"));
        //
        System.out.println(assistant.mood("我今天吃了冰淇凌，真好吃呀"));
        System.out.println(assistant.mood("冰淇凌掉地上了。。。"));
        System.out.println(assistant.mood("踩到狗屎了，完蛋"));
        // // 实际上是通过prompt来约束LLM："我很生气\nYou must answer strictly with one of these enums:\nHAPPY\nSAD\nANGRY"
        System.out.println(assistant.mood("我很生气"));

        System.out.println(assistant.chatWithAi("rust"));

        System.out.println(assistant.getUserInfo("你好，我叫谢阿花，我出生于1999年7月份，我爱抽烟喝酒烫头"));
    }

    interface Assistant {
        @UserMessage("请使用{{userQ}}语言实现冒泡排序")
        @SystemMessage("你叫谢阿花，是一个程序员。")
        String chat(@V("userQ") String question);


        @UserMessage("请使用{{userQ}}语言实现冒泡排序")
        @SystemMessage("你叫谢阿花，是一个程序员。")
        AiMessage chatWithAi(@V("userQ") String question);

        /**
         * 返回枚举（其实都是通过prompt对LLM的输出进行约束）
         * 作用：对文本进行分类，例如情感、用户意图等
         *
         * @param msg
         * @return
         */
        Mood mood(String msg);

        /**
         * 直接解析为POJO类
         *
         * @param description
         * @return
         */
        User getUserInfo(String description);

    }

    @Getter
    @Setter
    @ToString
    static class User {
        /**
         * 可以加一些描述
         */
        @Description("姓名，名字")
        private String name;
        private int age;
        private String[] hobby;
    }

    @AllArgsConstructor
    enum Mood {
        /**
         * 开心
         * 通过注解来描述，会被发给大模型，且这个描述不要太短，否则大模型认为描述也是枚举的一部分，会随枚举返回，导致转为枚举失败
         */
        @Description("表示心情非常好，开心")
        HAPPY,
        /**
         * 难过
         */
        @Description("表示心情很差，难过")
        SAD,
        /**
         * 生气
         */
        @Description("表示很被惹恼，很生气")
        ANGRY;

    }
}
